﻿using Mapster;
using Shop.Core.Consts;
using Shop.Core.Repository;
using Shop.Core.Share;
using Shop.IServices;
using Shop.Model.Dto.Car;
using Shop.Model.Dto.Goo;
using Shop.Model.Entity.Goo;
using Shop.Model.Entity.Use;
using Shop.Model.View.Car;
using SqlSugar;

namespace Shop.Services;

public class ShopCartAppService: IShopCartAppService
{
    private readonly RepositoryBase<GoodsCart> _cartRepository;
    private readonly RepositoryBase<GoodsGoods> _goodsRepository;
    private readonly RepositoryBase<GoodsSize> _sizeRepository;
    
    public ShopCartAppService(RepositoryBase<GoodsCart> cartRepository,
        RepositoryBase<GoodsGoods> goodsRepository, 
        RepositoryBase<GoodsSize> sizeRepository)
    {
        _cartRepository = cartRepository;
        _goodsRepository = goodsRepository;
        _sizeRepository = sizeRepository;
    }

    /// <summary>
    /// 添加商品到购物车
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    public AppResult<bool> AddProduct(long uId, ProductAddDto dto)
    {
        var goodSizeInfo = _sizeRepository.Where(x => x.Id == dto.Size && x.GoodsId == dto.Goods && x.Valid == true)
            .First();
        if (goodSizeInfo == null)
            throw new Exception("商品数据错误");
        var data = _cartRepository.Where(x => x.User == uId && x.Goods == dto.Goods && x.Size == dto.Size).First();
        if (data != null)
        {
            data.Count += dto.Count;
            _cartRepository.Update(data);
        }
        else
        {
            var goodsCart = dto.Adapt<GoodsCart>();
            goodsCart.User = uId;
            _cartRepository.Insert(goodsCart);
        }
        return true;
    }

    /// <summary>
    /// 删除购物车商品
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    public AppResult<bool> DeleteProduct(long uId, DeleteProductDto dto)
    {
        var data = _cartRepository.Where(x => x.User == uId && dto.CId.Contains(x.Id)).ToList();
        if (data.Count > 0)
        {
            _cartRepository.Delete(data);
        }
        return true;
    }

    /// <summary>
    /// 修改购物车商品规格
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    public AppResult<bool> UpdateProduct(long uId, ProductModifyDto dto)
    {
        var size = _sizeRepository.Where(x => x.Id == dto.Size).Select(x => x.GoodsId).First();
        if (size != dto.Goods)
            throw new Exception("商品规格数据错误");
        var data = _cartRepository.Where(x => x.User == uId && x.Goods == dto.Goods && x.Size == dto.Size).First();
        if (data != null)
        {
            if (data.Id != dto.Id)
            {
                data.Count++;
                _cartRepository.Update(data);
                _cartRepository.DeleteById(dto.Id);
            }
        }
        else
        {
            _cartRepository.AsUpdateable()
                .Where(x => x.Id == dto.Id)
                .SetColumns(x => x.Size == dto.Size)
                .ExecuteCommand();
        }
        return true;
    }
    
    /// <summary>
    /// 商品规格集合
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    public AppResult<GooSizeVo> GooSize(long uId, GooSizeDto dto)
    {
        var isZh = dto.language.Equals(LanguageConsts.ZH);
        var useGrade = _cartRepository.Queryable<UseUser>().Where(x => x.Id == uId).Select(x => x.Grade).First();
        var data = _goodsRepository.Includes(x => x.Size, y=>y.Price)
            .Where(x => x.Id == dto.gId)
            .ToList(x => new GooSizeVo()
            {
                Spc = isZh ? x.Spc : x.UighurSpc,
                Size = x.Size.Select(z => new SizeVo()
                {
                    Sid = z.Id,
                    Name = isZh ? z.Name : z.UighurName,
                    Money = useGrade == 0 ? z.Price.Price :
                        useGrade == 1 ? z.Price.OnePrice :
                        useGrade == 2 ? z.Price.TwoPrice : z.Price.ThreePrice,
                    Img = z.Thumbnail,
                    Count = z.Stock
                }).ToList()
            }).First();
        return data;
    }

    /// <summary>
    /// 修改购物车商品数量
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult<bool> UpdateCount(long uId, UpdateCountDto dto)
    {
        if (dto.Count < 1)
            throw new Exception("数量不能少于1");
        var data = _cartRepository.Where(x => x.Id == dto.CId && x.User == uId).First();
        if (data == null)
            throw new Exception("购物车信息错误");
        data.Count = dto.Count;
        _cartRepository.Update(data);
        return true;
    }

    /// <summary>
    /// 获取用户购物车商品信息
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="language"></param>
    /// <returns></returns>
    public async Task<PageModel<ProductListVo>> GetProductList(long uId, PageSearchModel<string> language)
    {
        var isZh = language.Equals(LanguageConsts.ZH);
        RefAsync<int> pageRecords = 0;
        var useGrade = _cartRepository.Queryable<UseUser>().Where(x => x.Id == uId).Select(x => x.Grade).First();
        var data = await _cartRepository.Queryable<GoodsCart, GoodsSize, GoodsGoods, GoodsPrice>((t1, t2, t3, t4) =>
                new object[]
                {
                    JoinType.Left, t1.Size == t2.Id,
                    JoinType.Left, t1.Goods == t3.Id,
                    JoinType.Left, t2.Id == t4.Size
                })
            .OrderBy((t1, t2, t3, t4) => t1.Id)
            .Select((t1, t2, t3, t4) => new ProductListVo()
            {
                Id = t1.Id,
                Img = t2.Thumbnail,
                Name = isZh ? t3.Name : t3.UighurName,
                GId = t1.Goods,
                SId = t1.Size,
                SName = isZh ? t2.Name : t2.UighurName,
                Money = useGrade == 0 ? t4.Price :
                    useGrade == 1 ? t4.OnePrice :
                    useGrade == 2 ? t4.TwoPrice : t4.ThreePrice,
                Count = t1.Count,
                Stock = t2.Stock,
                IsValid = t3.Valid
            })
            .ToPageListAsync(language.PageIndex, language.PageSize, pageRecords);
        return new PageModel<ProductListVo>(language, data, pageRecords);
    }
}